package mobi.ilabs.restroom.storage;

import java.util.Map;
import java.util.TreeMap;

import mobi.ilabs.cache.CacheEntry;
import mobi.ilabs.cache.LRUCache;
import mobi.ilabs.restroom.domainmodel.ObjectValue;

import org.restlet.data.Request;

/**
 * An obval cache implementing an LRU eviction policy.
 *
 */
public final class ObvalCache extends LRUCache<ObjectValue> {

    private final Map<String, CacheEntry<ObjectValue>> filenameMap
        = new TreeMap<String, CacheEntry<ObjectValue>>();
    
    private final Storage storage;

    public ObvalCache(int maximumSize, final Storage s) {
        super(maximumSize);
        storage = s;
    }

    @Override
    protected long getSize(ObjectValue t) {
        return t.getSize();
    }

    @Override
    protected ObjectValue getFromBacking(final Request request, final String obidString) {
        return storage.getValueByObid(request, ObjectValue.decodeObidString(obidString));
    }

    @Override
    public synchronized CacheEntry<ObjectValue> remove(CacheEntry<ObjectValue> entry) {
        assert(entry != null);
        assert(entry.getContent() != null);
        final String filename = entry.getContent().getFilepath();
        if (filename != null) {
            filenameMap.remove(filename);
        }
        return super.remove(entry);
    }

    @Override
    public synchronized CacheEntry<ObjectValue> put(String key, ObjectValue ob) {
        final CacheEntry<ObjectValue>  myEntry =  super.put(key, ob);
        final String  fn = ob.getFilepath();
        if (fn != null) {
            filenameMap.put(fn, myEntry);
        }
        return myEntry;
    }


    public synchronized ObjectValue getFromFilename(final Request r, final String filename) {
        final CacheEntry<ObjectValue> e = filenameMap.get(filename);
        if (e != null) {
            return e.getContent();
        } else {
            final String obid = storage.getObidFromFilename(r, filename);
            if (obid != null) {
                return get(r, obid);
            } else {
                return null;
            }
        }
    }


    public boolean hasFilenameCached(Request r, final String filename) {
        return filenameMap.containsKey(filename);
    }

    public String getCachedObidFromFilename(Request r, final String filename){
        return filenameMap.get(filename).getContent().getIdString();
    }
}